package com.easylinkin.linkappapi.positioning.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.linkappapi.gaodemap.entity.GeoFence;
import com.easylinkin.linkappapi.gaodemap.entity.GeoFenceApiResult;
import com.easylinkin.linkappapi.gaodemap.service.GaoDeApiService;
import com.easylinkin.linkappapi.positioning.entity.AlarmConfig;
import com.easylinkin.linkappapi.positioning.entity.AlarmDeviceConfig;
import com.easylinkin.linkappapi.positioning.entity.AlarmPersonContact;
import com.easylinkin.linkappapi.positioning.entity.ElectronicFence;
import com.easylinkin.linkappapi.positioning.mapper.AlarmConfigMapper;
import com.easylinkin.linkappapi.positioning.mapper.AlarmDeviceConfigMapper;
import com.easylinkin.linkappapi.positioning.mapper.SbdwAlarmPersonContactMapper;
import com.easylinkin.linkappapi.positioning.mapper.ElectronicFenceMapper;
import com.easylinkin.linkappapi.positioning.service.ElectronicFenceService;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import site.morn.rest.RestBuilders;
import site.morn.rest.RestMessage;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @program: linkapp-group
 * @description: ~
 * @author: chenkaixuan
 * @create: 2021-07-27 11:39
 */
@Service
public class ElectronicFenceServiceImpl extends ServiceImpl<ElectronicFenceMapper, ElectronicFence> implements ElectronicFenceService {
    @Resource
    LinkappUserContextProducer linkappUserContextProducer;
    @Resource
    GaoDeApiService gaoDeApiService;
    @Resource
    AlarmDeviceConfigMapper alarmDeviceConfigMapper;
    @Resource
    AlarmConfigMapper alarmConfigMapper;
    @Resource
    SbdwAlarmPersonContactMapper sbdwAlarmPersonContactMapper;


    /***
     * 新增围栏
     * @param electronicFence
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveElectronicFence(ElectronicFence electronicFence){
        Assert.notNull(electronicFence,"参数不能为空");
        Assert.notNull(electronicFence.getName(),"name 不能为空");
        String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
        //效验重复
        QueryWrapper<ElectronicFence> electronicFenceQueryWrapper = new QueryWrapper<>();
        electronicFenceQueryWrapper.eq("tenant_id",tenantId);
        electronicFenceQueryWrapper.eq("name",electronicFence.getName());
        Integer selectCount = baseMapper.selectCount(electronicFenceQueryWrapper);
        if(selectCount!= null && selectCount>0){
            throw new IllegalArgumentException(electronicFence.getName()+" 名称已存在");
        }
        electronicFence.setTenantId(tenantId);
        electronicFence.setUpdateTime(new Date());
        save(electronicFence);
    }

    /***
     * 围栏设置
     * @param electronicFence
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public RestMessage configElectronicFence(ElectronicFence electronicFence) throws Exception {
        Assert.notNull(electronicFence,"参数不能为空");
        Assert.notEmpty(electronicFence.getIds(),"ids 不能为空");
        Assert.notNull(electronicFence.getType(),"type 不能为空");
        if(electronicFence.getType().intValue() == 1 && (StringUtils.isEmpty(electronicFence.getCenter()) || StringUtils.isEmpty(electronicFence.getRadius()))){
            throw new IllegalArgumentException("center和radius 不能为空");
        }
        if(electronicFence.getType().intValue() == 2 && (electronicFence.getPoints()==null || electronicFence.getPoints().size()<=0)){
            throw new IllegalArgumentException("points 不能为空");
        }
        for (Integer id:electronicFence.getIds()){
            //检测
            ElectronicFence originElectronicFence = getById(id);
            if(StringUtils.isEmpty(originElectronicFence)){
                throw new IllegalArgumentException("id:"+id+" 不存在");
            }
            //如果围栏类型不一致，则删除后新增
            if(!StringUtils.isEmpty(originElectronicFence.getGid()) && !electronicFence.getType().equals(originElectronicFence.getType())){
                GeoFence geoFence=new GeoFence();
                geoFence.setGfids(Arrays.asList(originElectronicFence.getGid()));
                gaoDeApiService.delete(geoFence);
                originElectronicFence.setGid(null);
            }
            //创建围栏
            GeoFence geoFence=new GeoFence();
            geoFence.setName(originElectronicFence.getName()+"_"+originElectronicFence.getTenantId()+"_"+originElectronicFence.getId());
            geoFence.setDesc(electronicFence.getRemarks());
            if(!StringUtils.isEmpty(originElectronicFence.getGid())){
                geoFence.setGfid(originElectronicFence.getGid());
            }
            GeoFenceApiResult geoFenceApiResult=null;
            if(electronicFence.getType().intValue() == 1){
                geoFence.setCenter(electronicFence.getCenter());
                geoFence.setRadius(electronicFence.getRadius());
                geoFenceApiResult= gaoDeApiService.addOrUpdateCircle(geoFence);
            }else if(electronicFence.getType().intValue() == 2){
                geoFence.setPoints(String.join(";",electronicFence.getPoints()));
                geoFenceApiResult=gaoDeApiService.addOrUpdatePolygon(geoFence);
            }
            if(!StringUtils.isEmpty(originElectronicFence.getGid())){
                if(geoFenceApiResult == null){
                    return  RestBuilders.failureMessage();
                }
            }else{
                if(geoFenceApiResult == null || geoFenceApiResult.getData() == null || StringUtils.isEmpty(geoFenceApiResult.getData().getGfid())){
                    return  RestBuilders.failureMessage();
                }
                //保存数据库
                originElectronicFence.setGid(geoFenceApiResult.getData().getGfid());
                originElectronicFence.setUpdateTime(new Date());
                originElectronicFence.setType(electronicFence.getType());
                saveOrUpdate(originElectronicFence);
            }
        }
        return  RestBuilders.successMessage();
    }

    /***
     * 获取电子围栏列表
     * @param electronicFence
     * @return
     * @throws Exception
     */
    @Override
    public List<ElectronicFence> electronicFenceList(ElectronicFence electronicFence) throws Exception {
        String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
        QueryWrapper<ElectronicFence> electronicFenceQueryWrapper = new QueryWrapper<>();
        electronicFenceQueryWrapper.eq("tenant_id",tenantId);
        if(!StringUtils.isEmpty(electronicFence.getName())){
            electronicFenceQueryWrapper.like("name",electronicFence.getName());
        }
        List<ElectronicFence> electronicFenceList = list(electronicFenceQueryWrapper);
        if(electronicFenceList == null || electronicFenceList.size()<=0){
            return null;
        }
        List<String> gfids = electronicFenceList.parallelStream().map(i -> i.getGid()).filter(i -> !StringUtils.isEmpty(i)).collect(Collectors.toList());
        GeoFence geoFence=new GeoFence();
        geoFence.setGfids(gfids);
        GeoFenceApiResult geoFenceApiResult = gaoDeApiService.list(geoFence);
        if(geoFenceApiResult == null || geoFenceApiResult.getData() == null || geoFenceApiResult.getData() == null){
            return  electronicFenceList;
        }
        List<GeoFenceApiResult.GeoFenceApiResultData.GeoFenceApiResultDataResults> results = geoFenceApiResult.getData().getResults();
        if(results == null || results.size()<=0){
            return  electronicFenceList;
        }
        //获取围栏坐标
        Map<String, GeoFenceApiResult.GeoFenceApiResultData.GeoFenceApiResultDataResults.Shape> shapeMap = results.parallelStream()
                .collect(Collectors.toMap(m -> m.getGfid(), m -> m.getShape(), (k1, k2) -> k1));
        electronicFenceList.parallelStream().forEach(i->{
            if(StringUtils.isEmpty(i.getGid())){
                return;
            }
            GeoFenceApiResult.GeoFenceApiResultData.GeoFenceApiResultDataResults.Shape shape = shapeMap.get(i.getGid());
            if(shape == null){
                return;
            }
            i.setCenter(shape.getCenter());
            i.setRadius(shape.getRadius());
            if(!StringUtils.isEmpty(shape.getPoints())){
                String[] split = shape.getPoints().split(";");
                if(split != null && split.length>0){
                    i.setPoints(Arrays.asList(split));
                }
            }
        });
        return electronicFenceList;
    }

    /***
     * 删除
     * @param electronicFence
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public  RestMessage deleteElectronicFence(ElectronicFence electronicFence) throws Exception {
        Assert.notNull(electronicFence,"参数不能为空");
        Assert.notEmpty(electronicFence.getIds(),"ids 不能为空");
        Collection<ElectronicFence> electronicFences = listByIds(electronicFence.getIds());
        if(electronicFences == null || electronicFences.size()<=0){
            return RestBuilders.failureMessage().setMessage("数据不存在");
        }
        List<String> collect = electronicFences.stream().map(i -> i.getGid()).filter(i->!StringUtils.isEmpty(i)).collect(Collectors.toList());
        List<String> gfids=new ArrayList<>();
        if(collect != null && collect.size()>0){
            GeoFence geoFence=new GeoFence();
            geoFence.setGfids(collect);
            GeoFenceApiResult  delete = gaoDeApiService.delete(geoFence);
            if(delete != null && delete.getData() != null && delete.getData().getGfids() != null && delete.getData().getGfids().size()>0){
                gfids.addAll(delete.getData().getGfids());
            }
        }
        //直接删除，不做gfids判断
        List<Integer> ids = electronicFences.stream().filter(i -> (StringUtils.isEmpty(i.getGid()) || collect.contains(i.getGid()))).map(i -> i.getId()).collect(Collectors.toList());
        removeByIds(ids);
        return  RestBuilders.successMessage();
    }

    @Override
    public  List<ElectronicFence> getAlarmConfigByIds(ElectronicFence electronicFence){
        Assert.notNull(electronicFence,"参数不能为空");
        Assert.notEmpty(electronicFence.getIds(),"ids 不能为空");
        List<ElectronicFence> electronicFenceList = baseMapper.getElectronicFenceList(electronicFence);
        return electronicFenceList;
    }

    @Override
    public  ElectronicFence getAlarmConfigById(ElectronicFence electronicFence){
        Assert.notNull(electronicFence,"参数不能为空");
        Assert.notNull(electronicFence.getId(),"id 不能为空");
        List<ElectronicFence> electronicFenceList = baseMapper.getElectronicFenceList(electronicFence);
        if(electronicFenceList == null || electronicFenceList.size()<=0){
            return null;
        }
        return electronicFenceList.get(0);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveAlarmConfig(ElectronicFence electronicFence){
        Assert.notNull(electronicFence,"参数不能为空");
        Assert.notEmpty(electronicFence.getIds(),"ids 不能为空");
        Collection<ElectronicFence> electronicFences = listByIds(electronicFence.getIds());
        if(electronicFences == null || electronicFences.size()!=electronicFence.getIds().size()){
            throw new IllegalArgumentException("ids 不能缺失或不存在");
        }

        String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
        electronicFence.setTenantId(tenantId);
        //删除关联
        removeRelation(electronicFence);
        //保存
        saveRelation(electronicFence);

        if(electronicFence.getIds().size() == 1){
            Integer id = electronicFence.getIds().get(0);
            electronicFences.forEach(i->{
                if(i.getId().equals(id) && !i.getName().equals(electronicFence.getName())){
                    //效验重复
                    QueryWrapper<ElectronicFence> electronicFenceQueryWrapper = new QueryWrapper<>();
                    electronicFenceQueryWrapper.eq("tenant_id",tenantId);
                    electronicFenceQueryWrapper.eq("name",electronicFence.getName());
                    Integer selectCount = baseMapper.selectCount(electronicFenceQueryWrapper);
                    if(selectCount!= null && selectCount>0){
                        throw new IllegalArgumentException(electronicFence.getName()+" 名称已存在");
                    }
                    //修改
                    UpdateWrapper<ElectronicFence> electronicFenceUpdateWrapper=new UpdateWrapper<>();
                    electronicFenceUpdateWrapper.set("name",electronicFence.getName());
                    electronicFenceUpdateWrapper.set("remarks",electronicFence.getRemarks());
                    electronicFenceUpdateWrapper.set("update_time",new Date());
                    electronicFenceUpdateWrapper.in("id",electronicFence.getIds());
                    update(electronicFenceUpdateWrapper);
                }
            });
        }

    }

    /***
     * 保存告警设置
     * @param electronicFence
     */
    private void saveRelation(ElectronicFence electronicFence){
        //设备
        List<AlarmDeviceConfig> alarmDeviceConfigList = electronicFence.getAlarmDeviceConfigList();
        List<AlarmDeviceConfig> insertAlarmDeviceConfigList=new ArrayList<>();
        //告警设置
        List<AlarmConfig> alarmConfigList = electronicFence.getAlarmConfigList();
        List<AlarmConfig> insertAlarmConfigList=new ArrayList<>();
                //联系人
        List<AlarmPersonContact> alarmPersonContactList = electronicFence.getAlarmPersonContactList();
        List<AlarmPersonContact> insertAlarmPersonContactList=new ArrayList<>();
        electronicFence.getIds().stream().forEach(i->{
            if(alarmDeviceConfigList != null && alarmDeviceConfigList.size()>0){
                alarmDeviceConfigList.stream().forEach(alarm -> {
                    alarm.setFenceId(i);
                });
                insertAlarmDeviceConfigList.addAll(alarmDeviceConfigList);
            }
            if(alarmConfigList != null && alarmConfigList.size()>0){
                alarmConfigList.stream().forEach(alarmConfig -> {
                    alarmConfig.setFenceId(i);
                });
                insertAlarmConfigList.addAll(alarmConfigList);
            }
            if(alarmPersonContactList != null && alarmPersonContactList.size()>0){
                alarmPersonContactList.stream().forEach(personContact -> {
                    personContact.setFenceId(i);
                });
                insertAlarmPersonContactList.addAll(alarmPersonContactList);
            }
        });
        if(insertAlarmDeviceConfigList != null && insertAlarmDeviceConfigList.size()>0){
            alarmDeviceConfigMapper.batchInsert(insertAlarmDeviceConfigList);
        }
        if(insertAlarmConfigList != null && insertAlarmConfigList.size()>0){
            alarmConfigMapper.batchInsert(insertAlarmConfigList);
        }
        if(insertAlarmPersonContactList != null && insertAlarmPersonContactList.size()>0){
            sbdwAlarmPersonContactMapper.batchInsert(insertAlarmPersonContactList);
        }
    }

    private void removeRelation(ElectronicFence electronicFence){
        //删除关联设备
        QueryWrapper<AlarmDeviceConfig> alarmDeviceConfigQueryWrapper=new QueryWrapper<>();
        alarmDeviceConfigQueryWrapper.in("fence_id",electronicFence.getIds());
        //alarmDeviceConfigQueryWrapper.eq("tenant_id",electronicFence.getTenantId());
        alarmDeviceConfigMapper.delete(alarmDeviceConfigQueryWrapper);
        //删除告警设置
        QueryWrapper<AlarmConfig> alarmConfigQueryWrapper = new QueryWrapper<>();
        alarmConfigQueryWrapper.in("fence_id",electronicFence.getIds());
        //alarmConfigQueryWrapper.eq("tenant_id",electronicFence.getTenantId());
        alarmConfigMapper.delete(alarmConfigQueryWrapper);
        //删除告警联系人
        QueryWrapper<AlarmPersonContact> alarmPersonContactQueryWrapper = new QueryWrapper<>();
        alarmPersonContactQueryWrapper.in("fence_id",electronicFence.getIds());
        //alarmPersonContactQueryWrapper.eq("tenant_id",electronicFence.getTenantId());
        sbdwAlarmPersonContactMapper.delete(alarmPersonContactQueryWrapper);
    }
}
